﻿using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Controls.Primitives;
using System.Windows.Automation.Peers;
using Gmantis.Controls.Automation;
using System.Globalization;

namespace Gmantis.Controls.Extended
{
    [TemplateVisualState(Name = "Left", GroupName = "DirectionStates"), TemplateVisualState(Name = "Expanded", GroupName = "ExpansionStates"), TemplateVisualState(Name = "Right", GroupName = "DirectionStates"), TemplatePart(Name = "ExpandButton", Type = typeof(ToggleButton)), TemplateVisualState(Name = "Collapsed", GroupName = "ExpansionStates"), TemplateVisualState(Name = "Up", GroupName = "DirectionStates"), TemplateVisualState(Name = "Down", GroupName = "DirectionStates")]
    public class Expander : HeaderedContentControl
    {
        // Fields
        internal ToggleButton _elementExpandButton;
        private AutomationPeer _peer;
        private bool _throwIsExpandedChanged;
        public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(Expander), new PropertyMetadata(new CornerRadius(0.0)));
        public static readonly DependencyProperty DisabledBrushProperty = DependencyProperty.Register("DisabledBrush", typeof(Brush), typeof(Expander), null);
        internal const string ExpandButtonElementName = "ExpandButton";
        public static readonly DependencyProperty ExpandDirectionProperty = DependencyProperty.Register("ExpandDirection", typeof(ExpandDirection), typeof(Expander), new PropertyMetadata(ExpandDirection.Down, new PropertyChangedCallback(Expander.OnExpandDirectionPropertyChanged)));
        public static readonly DependencyProperty ExpandedBackgroundProperty = DependencyProperty.Register("ExpandedBackground", typeof(Brush), typeof(Expander), null);
        public static readonly DependencyProperty FocusBrushProperty = DependencyProperty.Register("FocusBrush", typeof(Brush), typeof(Expander), null);
        public static readonly DependencyProperty IsExpandableProperty = DependencyProperty.Register("IsExpandable", typeof(bool), typeof(Expander), new PropertyMetadata(true));
        public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register("IsExpanded", typeof(bool), typeof(Expander), new PropertyMetadata(new PropertyChangedCallback(Expander.OnIsExpandedPropertyChanged)));
        public static readonly DependencyProperty MouseOverBrushProperty = DependencyProperty.Register("MouseOverBrush", typeof(Brush), typeof(Expander), null);

        // Events
        public event EventHandler<PropertyChangedEventArgs<bool>> IsExpandedChanged;
        public event EventHandler<PropertyChangingEventArgs<bool>> IsExpandedChanging;

        // Methods
        public Expander()
        {
            RoutedEventHandler handler = null;
            this._throwIsExpandedChanged = true;
            base.DefaultStyleKey = typeof(Expander);
            if (handler == null)
            {
                handler = delegate(object param0, System.Windows.RoutedEventArgs param1)
                {
                    this.ChangeVisualStateExpansion(false);
                    this.ChangeVisualStateDirection(false);
                };
            }
            base.Loaded += handler;
        }

        protected void ChangeVisualStateDirection(bool useTransitions)
        {
            if (this.ExpandDirection == ExpandDirection.Left)
            {
                VisualStateHelper.GoToState(this, "Left", useTransitions);
            }
            if (this.ExpandDirection == ExpandDirection.Right)
            {
                VisualStateHelper.GoToState(this, "Right", useTransitions);
            }
            if (this.ExpandDirection == ExpandDirection.Up)
            {
                VisualStateHelper.GoToState(this, "Up", useTransitions);
            }
            if (this.ExpandDirection == ExpandDirection.Down)
            {
                VisualStateHelper.GoToState(this, "Down", useTransitions);
            }
        }

        protected void ChangeVisualStateExpansion(bool useTransitions)
        {
            if (!this.IsExpanded)
            {
                VisualStateHelper.GoToState(this, "Collapsed", useTransitions);
            }
            if (this.IsExpanded)
            {
                VisualStateHelper.GoToState(this, "Expanded", useTransitions);
            }
        }

        private T GetTemplateChild<T>(string childName, bool required, ref string errors) where T : class
        {
            DependencyObject templateChild = base.GetTemplateChild(childName);
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "template part", childName, templateChild, required, ref errors);
            return (templateChild as T);
        }

        private static Storyboard GetTemplateChildResource(FrameworkElement root, string resourceName, bool required, ref string errors)
        {
            return GetTemplateChildResource<Storyboard>(root, resourceName, required, ref errors);
        }

        private static T GetTemplateChildResource<T>(FrameworkElement root, string resourceName, bool required, ref string errors) where T : class
        {
            object child = root.Resources[resourceName];
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "resource", resourceName, child, required, ref errors);
            return (child as T);
        }

        private void OnAfterApplyTemplate()
        {
            this._elementExpandButton.IsThreeState = false;
            this._elementExpandButton.IsChecked = new bool?(this.IsExpanded);
            this._elementExpandButton.Click += new RoutedEventHandler(this.OnExpandButtonClick);
        }

        public override void OnApplyTemplate()
        {
            this.OnBeforeApplyTemplate();
            string errors = string.Empty;
            base.OnApplyTemplate();
            this._elementExpandButton = this.GetTemplateChild<ToggleButton>("ExpandButton", true, ref errors);
            if (!string.IsNullOrEmpty(errors))
            {
                if ((base.Template != null) && !PlatformIndependent.IsInDesignMode(this))
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Template cannot be applied to Expander.\nDetails: {0}", new object[] { errors }));
                }
            }
            else
            {
                this.ChangeVisualStateExpansion(false);
                this.ChangeVisualStateDirection(false);
                this.OnAfterApplyTemplate();
            }
        }

        private void OnBeforeApplyTemplate()
        {
        }

        protected override AutomationPeer OnCreateAutomationPeer()
        {
            if (this._peer == null)
            {
                this._peer = AutomationPeerFactory.CreateAutomationPeer(this, typeof(Expander));
            }
            if (this._peer == null)
            {
                return base.OnCreateAutomationPeer();
            }
            return this._peer;
        }

        private void OnExpandButtonClick(object sender, System.Windows.RoutedEventArgs e)
        {
            if (this.IsExpandable && this._elementExpandButton.IsChecked.HasValue)
            {
                bool flag = this._elementExpandButton.IsChecked.Value;
                PropertyChangingEventArgs<bool> args = new PropertyChangingEventArgs<bool>
                {
                    OldValue = this.IsExpanded,
                    NewValue = flag
                };
                if (this.IsExpandedChanging != null)
                {
                    this.IsExpandedChanging(this, args);
                }
                if (!args.Cancel)
                {
                    this.IsExpanded = flag;
                }
                else
                {
                    this._elementExpandButton.IsChecked = new bool?(this.IsExpanded);
                }
            }
        }

        private static void OnExpandDirectionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as Expander).ChangeVisualStateDirection(true);
        }

        private void OnIsExpandedChanged(bool oldValue)
        {
            if (this._elementExpandButton != null)
            {
                this._elementExpandButton.IsChecked = new bool?(this.IsExpanded);
            }
        }

        private static void OnIsExpandedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Expander sender = d as Expander;
            bool oldValue = (bool)e.OldValue;
            sender.OnIsExpandedChanged(oldValue);
            if ((sender.IsExpandedChanged != null) && sender._throwIsExpandedChanged)
            {
                PropertyChangedEventArgs<bool> args = new PropertyChangedEventArgs<bool>
                {
                    OldValue = (bool)e.OldValue,
                    NewValue = (bool)e.NewValue
                };
                sender.IsExpandedChanged(sender, args);
            }
            sender.ChangeVisualStateExpansion(true);
        }

        // Properties
        public CornerRadius CornerRadius
        {
            get
            {
                return (CornerRadius)base.GetValue(CornerRadiusProperty);
            }
            set
            {
                base.SetValue(CornerRadiusProperty, value);
            }
        }

        public Brush DisabledBrush
        {
            get
            {
                return (Brush)base.GetValue(DisabledBrushProperty);
            }
            set
            {
                base.SetValue(DisabledBrushProperty, value);
            }
        }

        public ExpandDirection ExpandDirection
        {
            get
            {
                return (ExpandDirection)base.GetValue(ExpandDirectionProperty);
            }
            set
            {
                base.SetValue(ExpandDirectionProperty, value);
            }
        }

        public Brush ExpandedBackground
        {
            get
            {
                return (Brush)base.GetValue(ExpandedBackgroundProperty);
            }
            set
            {
                base.SetValue(ExpandedBackgroundProperty, value);
            }
        }

        public Brush FocusBrush
        {
            get
            {
                return (Brush)base.GetValue(FocusBrushProperty);
            }
            set
            {
                base.SetValue(FocusBrushProperty, value);
            }
        }

        public bool IsExpandable
        {
            get
            {
                return (bool)base.GetValue(IsExpandableProperty);
            }
            set
            {
                base.SetValue(IsExpandableProperty, value);
            }
        }

        public bool IsExpanded
        {
            get
            {
                return (bool)base.GetValue(IsExpandedProperty);
            }
            set
            {
                base.SetValue(IsExpandedProperty, value);
            }
        }

        public Brush MouseOverBrush
        {
            get
            {
                return (Brush)base.GetValue(MouseOverBrushProperty);
            }
            set
            {
                base.SetValue(MouseOverBrushProperty, value);
            }
        }
    }
}
